package com.dragon.modules.yuegou.service.impl.member;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.exception.DragonException;
import com.dragon.common.web.PageRequest;
import com.dragon.modules.media.workbook.validate.ValidateResult;
import com.dragon.modules.yuegou.entity.busd.BtypeEntity;
import com.dragon.modules.yuegou.entity.member.DistrictMemberEntity;
import com.dragon.modules.yuegou.entity.member.FavoriteEntity;
import com.dragon.modules.yuegou.entity.member.MemberEntity;
import com.dragon.modules.yuegou.entity.member.WxOpenidRefEntity;
import com.dragon.modules.yuegou.entity.merchant.MerchantEntity;
import com.dragon.modules.yuegou.entity.order.OrderEntity;
import com.dragon.modules.yuegou.entity.park.PlateNoEntity;
import com.dragon.modules.yuegou.entity.product.HelpEntity;
import com.dragon.modules.yuegou.entity.product.SkuEntity;
import com.dragon.modules.yuegou.enums.YsqAppType;
import com.dragon.modules.yuegou.enums.code.BusinessCode;
import com.dragon.modules.yuegou.enums.code.DistrictCode;
import com.dragon.modules.yuegou.enums.code.MemberCode;
import com.dragon.modules.yuegou.enums.code.PayCode;
import com.dragon.modules.yuegou.enums.coupon.CouponType;
import com.dragon.modules.yuegou.enums.member.FavoriteType;
import com.dragon.modules.yuegou.enums.member.MemberGender;
import com.dragon.modules.yuegou.enums.member.WxOpenidRefOpenIdType;
import com.dragon.modules.yuegou.enums.product.GrouponInfoCheckStatus;
import com.dragon.modules.yuegou.enums.product.GrouponInfoStatus;
import com.dragon.modules.yuegou.enums.product.HelpCheckStatus;
import com.dragon.modules.yuegou.enums.product.HelpStatus;
import com.dragon.modules.yuegou.excel.member.ExportMemberWorkbook;
import com.dragon.modules.yuegou.excel.member.MemberWorkbook;
import com.dragon.modules.yuegou.mapper.member.MemberMapper;
import com.dragon.modules.yuegou.model.member.DistrictMember;
import com.dragon.modules.yuegou.model.member.Favorite;
import com.dragon.modules.yuegou.model.member.Member;
import com.dragon.modules.yuegou.model.member.MemberCardLevel;
import com.dragon.modules.yuegou.model.member.MerchantList;
import com.dragon.modules.yuegou.model.member.ReportQuery;
import com.dragon.modules.yuegou.model.member.TemplatePretend;
import com.dragon.modules.yuegou.model.member.UserInfoModel;
import com.dragon.modules.yuegou.model.member.UserReportModel;
import com.dragon.modules.yuegou.model.member.WxOpenidRef;
import com.dragon.modules.yuegou.model.order.Order;
import com.dragon.modules.yuegou.model.park.PlateNo;
import com.dragon.modules.yuegou.model.product.GrouponInfo;
import com.dragon.modules.yuegou.model.product.ProductFavorite;
import com.dragon.modules.yuegou.model.system.Application;
import com.dragon.modules.yuegou.model.system.Document;
import com.dragon.modules.yuegou.query.member.DistrictMemberQuery;
import com.dragon.modules.yuegou.query.member.FavoriteQuery;
import com.dragon.modules.yuegou.query.member.MemberLevelQuery;
import com.dragon.modules.yuegou.query.member.MemberQuery;
import com.dragon.modules.yuegou.query.member.PasswordQuery;
import com.dragon.modules.yuegou.query.member.TemplatePretendQuery;
import com.dragon.modules.yuegou.query.member.WxOpenidRefQuery;
import com.dragon.modules.yuegou.query.order.OrderQuery;
import com.dragon.modules.yuegou.query.park.HistoryQuery;
import com.dragon.modules.yuegou.query.park.PlateNoQuery;
import com.dragon.modules.yuegou.service.act.GiftService;
import com.dragon.modules.yuegou.service.busd.BtypeService;
import com.dragon.modules.yuegou.service.busd.DistrictService;
import com.dragon.modules.yuegou.service.coupon.CouponService;
import com.dragon.modules.yuegou.service.member.DistrictMemberService;
import com.dragon.modules.yuegou.service.member.FavoriteService;
import com.dragon.modules.yuegou.service.member.LevelService;
import com.dragon.modules.yuegou.service.member.MemberCardLevelService;
import com.dragon.modules.yuegou.service.member.MemberService;
import com.dragon.modules.yuegou.service.member.TemplatePretendService;
import com.dragon.modules.yuegou.service.member.WxOpenidRefService;
import com.dragon.modules.yuegou.service.merchant.MerchantService;
import com.dragon.modules.yuegou.service.message.MessageService;
import com.dragon.modules.yuegou.service.order.OrderService;
import com.dragon.modules.yuegou.service.park.HistoryService;
import com.dragon.modules.yuegou.service.park.PlateNoService;
import com.dragon.modules.yuegou.service.points.DetailService;
import com.dragon.modules.yuegou.service.product.GrouponInfoService;
import com.dragon.modules.yuegou.service.product.HelpService;
import com.dragon.modules.yuegou.service.product.SkuService;
import com.dragon.modules.yuegou.service.system.ApplicationService;
import com.dragon.modules.yuegou.service.system.DocumentService;
import com.dragon.modules.yuegou.service.wallet.MemberCardService;
import com.dragon.modules.yuegou.service.wallet.MemberWalletService;
import com.dragon.modules.yuegou.utils.DateUtil;
import com.dragon.modules.yuegou.utils.EmojiUtil;
import com.dragon.modules.yuegou.utils.MD5Util;
import com.dragon.modules.yuegou.utils.PageToResultUtils;
import com.dragon.modules.yuegou.utils.PrivateStringUtils;
import com.dragon.modules.yuegou.utils.ReadExcelHelper;
import com.dragon.modules.yuegou.web.Check;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 会员信息 服务实现
 *
 * @author pbuilder generated
 * @date 2019-03-19 08:59:40
 * @version 2.0
 */
@Slf4j
@Service("memMemberService")
public class MemberServiceImpl extends ServiceImpl<MemberMapper, MemberEntity>
		implements MemberService {


	@Autowired
	private WxOpenidRefService wxOpenidRefService;

	@Autowired
	private DistrictMemberService districtMemberService;

	@Autowired
	private DistrictService districtService;

	@Autowired
	private ApplicationService applicationService;

	@Autowired
	private MemberMapper memberMapper;

	@Autowired
	private PlateNoService plateNoService;

	@Autowired
	private FavoriteService favoriteService;

	@Autowired
	private MerchantService merchantService;

	@Autowired
	private DocumentService documentService;

	@Autowired
	private LevelService levelService;

	@Autowired
	private CacheManager cacheManager;

	@Autowired
	private GrouponInfoService grouponInfoService;

	@Autowired
	private HelpService helpService;

	@Autowired
	private SkuService skuService;

	@Autowired
	private HistoryService historyService;

	@Autowired
	private OrderService orderService;

	@Autowired
	private BtypeService btypeService;

    @Autowired
    private GiftService giftService;

	@Autowired
	private TemplatePretendService templatePretendService;

	@Autowired
	private MemberWalletService memberWalletService;

	@Autowired
	private MemberCardService memberCardService;

	@Autowired
	private CouponService couponService;

	@Autowired
	private MessageService messageService;

	@Autowired
	private DetailService detailService;
	private Cache memberCache;

	/**
	 * member 缓存
	 */
	protected static final String MEMBER_CACHE = "memberCache";

	@Autowired
	private  MemberCardLevelService memberCardLevelService;


	@Autowired
	public void setMemberCacheManager(CacheManager cacheManager) {
		this.memberCache = cacheManager.getCache(MEMBER_CACHE);
	}


	@Override
	public Member getMember(String id) {
		Check.notNull(id, "id不能为空");
		MemberEntity member = getById(id);
		if (member != null) {
			if (StringUtils.isBlank(member.getNickName())) {
				member.setNickName(PrivateStringUtils.maskMobileNo(member.getMobile()));
			}else {
				member.setNickName(EmojiUtil.emojiRecovery2(member.getNickName()));
			}
		}

		return new Member(member);
	}

	@Override
	public Member createMember(Member member, String wxAppid, WxOpenidRefOpenIdType openIdType, YsqAppType current) {
		if (member == null) {
			throw new DragonException(MemberCode.MEMBER_NOT_EXIST);
		}
		// 验证手机号是否为空
		Check.notEmpty(member.getMobile(), PayCode.MOBILE_IS_EMPTY.getMessage());

		// 验证手机号是否存在
		Member newMember = this.getMemberByMobile(member.getMobile());
		if (newMember != null) {
			newMember.setWxOpenId(member.getWxOpenId());
			newMember.setWxUnionId(member.getWxUnionId());
			newMember.setAlipayAppid(member.getAlipayAppid());
			this.setMemberInformation(newMember, member.getBusdId(), wxAppid, openIdType);

			return newMember;
		}
		//根据unionId或者openId查询是否注册过会员
		Member oldMember = getMemberIdByRef(member, wxAppid);
		if (oldMember != null) {
			// 获取会员的会员卡等级信息
			memberCardLevelService.initMemberCardLevel(member.getBusdId(), member.getId());
			return oldMember;
		}
		// 不存在创建会员
		this.save(member);
		this.setMemberInformation(member, member.getBusdId(), wxAppid, openIdType);
		// 增加会员注册日志
		memberRegisteredLog(member);

		// 获取会员的会员卡等级信息
		return member;
	}

	private void memberRegisteredLog(Member member) {
		if (member != null) {
			Map<String, Object> logMap = new LinkedHashMap<>();
			logMap.put("head", "sgy_common_log");
			logMap.put("type", "register");
			logMap.put("data", member);
			log.info(JSON.toJSONString(logMap));
		}
	}

	private Member getMemberIdByRef(Member member,String wxAppid) {
		if (StringUtils.isNotEmpty(member.getWxUnionId())) {
			WxOpenidRefQuery query = new WxOpenidRefQuery();
			query.setWxUnionId(member.getWxUnionId());
			List<WxOpenidRefEntity> refList = wxOpenidRefService.list(query.toQueryWrapper());
			if (CollectionUtils.isNotEmpty(refList)){
				return this.getMember(refList.get(0).getMemberId());
			}
		}
		if (StringUtils.isNotEmpty(member.getWxOpenId()) && StringUtils.isNotEmpty(wxAppid)) {
			WxOpenidRefQuery query = new WxOpenidRefQuery();
			query.setWxOpenId(member.getWxOpenId());
			query.setAppid(wxAppid);
			List<WxOpenidRefEntity> refList = wxOpenidRefService.list(query.toQueryWrapper());
			if (CollectionUtils.isNotEmpty(refList)){
				return this.getMember(refList.get(0).getMemberId());
			}
		}else if (StringUtils.isNotEmpty(member.getAlipayAppid())){
			WxOpenidRefQuery query = new WxOpenidRefQuery();
			query.setAliAppid(member.getAlipayAppid());
			query.setAppid(wxAppid);
			List<WxOpenidRefEntity> refList = wxOpenidRefService.list(query.toQueryWrapper());
			if (CollectionUtils.isNotEmpty(refList)){
				return this.getMember(refList.get(0).getMemberId());
			}
		}
		return null;
	}

	@Override
	public String createMember(String busdId, String mobile, YsqAppType ysqAppType) {
		// 验证手机号是否为空
		Check.notEmpty(mobile, PayCode.MOBILE_IS_EMPTY.getMessage());
		// 验证手机号是否存在
		Member member = getMemberByMobile(mobile);
		if (member == null) {
			member = new Member();
			member.setMobile(mobile);
			member.setId(IdWorker.getIdStr());
			save(member);
		}
		createMemberDistrictRef(busdId, member.getId());

		// 获取会员的会员卡等级信息
		return member.getId();
	}

	private Member setMemberInformation(Member member, String busdId, String wxAppid,  WxOpenidRefOpenIdType openIdType) {
		if (StringUtils.isNotBlank(wxAppid)) {
			Application application = applicationService.getByWxAppid(wxAppid);
			if (application == null) {
				log.debug("找不到小程序应用信息，appid={}", wxAppid);
				throw new DragonException(PayCode.APPID_ERROR);
			}
			if (!WxOpenidRefOpenIdType.UNIAPP.equals(openIdType)){
				if (StringUtils.isEmpty(member.getAlipayAppid())){
					wxOpenidRefService.saveOrUpdate(member.getId(), member.getWxOpenId(), member.getWxUnionId(), wxAppid,openIdType);
				}else{
					wxOpenidRefService.saveOrUpdate(member.getId(), member.getAlipayAppid(),wxAppid,openIdType);
				}
			}
			// 添加会员openid对应关系数据
		}
		Boolean newMember = createMemberDistrictRef(busdId, member.getId());
		member.setNewMember(newMember);
		return member;
	}

	private boolean createMemberDistrictRef(String busdId, String memberId) {
		// 存在商圈id，判断商圈是否存在
		if (StringUtils.isNotEmpty(busdId)) {
			// 检查商圈ID
			districtService.checkBusdId(busdId);
			// 判断商圈会员是否存在，存在返回对象，不存在创建对象，并返回对象
			DistrictMember districtMember = districtMemberService.createDistrictMember(memberId, busdId);
			return districtMember.getNewMember();
		}
		return false;
	}

	@Override
	public Member getMemberByMobile(String mobile) {
		Check.notEmpty(mobile, PayCode.MOBILE_IS_EMPTY.getMessage());
		MemberQuery memberQuery = new MemberQuery();
		memberQuery.setMobile(mobile);
		List<MemberEntity> list = list(memberQuery.toQueryWrapper());
		if (CollectionUtils.isNotEmpty(list)){
			if (list.size() > 1) {
				throw new DragonException(PayCode.MOBILE_IS_REPEAT);
			} else if (list.size() == 1) {
				return getMember(list.get(0).getId());
			}
		}

		return null;
	}

	@Override
	public Member getMemberByWxUnionId(String wxUnionId) {
		if (StringUtils.isBlank(wxUnionId)) {
			return null;
		}
		WxOpenidRefQuery query = new WxOpenidRefQuery();
		query.setWxUnionId(wxUnionId);
		List<WxOpenidRefEntity> list = wxOpenidRefService.list(query.toQueryWrapper());
		if (CollectionUtils.isNotEmpty(list)) {
			String memberId = list.get(0).getMemberId();

			return this.getMember(memberId);
		}
		return null;
	}

	@Override
	public Member getMemberByWxOpenId(String wxOpenId, String appid) {
		if (StringUtils.isBlank(wxOpenId)) {
			return null;
		}
		// 判断会员是否存在
		WxOpenidRefQuery query = new WxOpenidRefQuery();
		query.setWxOpenId(wxOpenId);
		WxOpenidRef wxOpenidRef = wxOpenidRefService.getFirst(query);
		if (wxOpenidRef != null && wxOpenidRef.getMemberId() != null) {
			String memberId = wxOpenidRef.getMemberId();
			return this.getMember(memberId);
		}
		return null;
	}

	@Override
	public Member getMemberByWxUnionId(String wxUnionId, String appid) {
		if (StringUtils.isBlank(wxUnionId)) {
			return null;
		}
		// 判断会员是否存在
		WxOpenidRefQuery query = new WxOpenidRefQuery();
		query.setWxUnionId(wxUnionId);
		query.setAppid(appid);
		WxOpenidRef wxOpenidRef = wxOpenidRefService.getFirst(query);
		if (wxOpenidRef != null && wxOpenidRef.getMemberId() != null) {
			String memberId = wxOpenidRef.getMemberId();
			return this.getMember(memberId);
		}
		return null;
	}

	@Override
	public IPage<Member> search(PageRequest page, MemberLevelQuery query) {
		Check.notNull(query.getBusdId(), DistrictCode.DISTRICT_NOTNULL.getMessage());
		return memberMapper.search(PageToResultUtils.resultToPage(page), query);
	}

	@Override
	public Member getMemberById(String id, String busdId) {
		Check.notNull(id, MemberCode.MEMBER_ID_IS_EMPTY.getMessage());
		Check.notNull(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		Member member = memberMapper.getMemberById(id, busdId);
		PlateNoQuery query = new PlateNoQuery();
		query.setBusdId(busdId);
		query.setMemberId(id);
		query.setDel(false);
		List<PlateNoEntity> list = plateNoService.list(query.toQueryWrapper());
		if (CollectionUtils.isNotEmpty(list)) {
			member.setCarList(list.stream().map(PlateNo::new).collect(Collectors.toList()));
		}
		return member;
	}

	@Override
	public Document exportMember(MemberLevelQuery query) {
		Check.notNull(query.getBusdId(), DistrictCode.DISTRICT_NOTNULL.getMessage());
		List<Member> list = memberMapper.searchExport(query);
		MemberWorkbook memberWorkbook = new MemberWorkbook();
		List<MemberWorkbook.MemberRow> members = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(list)) {
			for (Member member : list) {
				MemberWorkbook.MemberRow memberRow = new MemberWorkbook.MemberRow();
				memberRow.setNickName(member.getNickName());
				memberRow.setMobile(member.getMobile());
				memberRow.setLevelName(member.getLevelName());
				memberRow.setMemPoints(member.getMemPoints());
				memberRow.setHistoryPoints(member.getHistoryPoints());
				memberRow.setYueCoin(member.getYueCoin());
				memberRow.setBusdMemberCreatedTime(member.getBusdMemberCreatedTime());
				memberRow.setAddress(member.getAddress());
				memberRow.setAge(member.getAge());
				memberRow.setBirthDay(member.getBirthDate());
				memberRow.setGender(member.getGender() == null ? MemberGender.UNKNOWN.getAlias() : member.getGender().getAlias());
				memberRow.setGrowCount(member.getGrowCount());
				memberRow.setOnlinePoints(member.getOnlinePoints());
				memberRow.setTotalPoints(member.getTotalPoints());
				members.add(memberRow);
			}
		}
		memberWorkbook.setMember(members);
		return documentService.generateExcel("会员信息表", memberWorkbook);
	}

	@Override
	public Member getMember(String busdId, String memberId) {
		Check.notEmpty(busdId, DistrictCode.DISTRICT_NOTNULL.getMessage());
		log.info("个人中心资料查看，开始==，商圈Id={}，会员Id={}", busdId, memberId);

		Member member = getMember(memberId);

		// 获得商圈会员信息 可用积分
		DistrictMemberQuery query = new DistrictMemberQuery();
		query.setBusdId(busdId);
		query.setMemberId(memberId);
		DistrictMemberEntity districtMember = districtMemberService.getOne(query.toQueryWrapper());
		if (districtMember == null) {
			createMemberDistrictRef(busdId,memberId);
			member.setMemPoints(0);
		}else {
			member.setMemPoints(districtMember.getMemPoints());
		}
		// 获取会员的会员卡等级信息
		MemberCardLevel cardLevelServiceOne = memberCardLevelService.initMemberCardLevel(busdId, memberId);
		if (cardLevelServiceOne !=null){
			member.setLevelName(cardLevelServiceOne.getGradeName());
			if (StringUtils.isNotEmpty(cardLevelServiceOne.getGradeId())){
				TemplatePretendQuery templatePretendQuery = new TemplatePretendQuery();
				templatePretendQuery.setTemplateGradeId(cardLevelServiceOne.getGradeId());
				TemplatePretend templatePretend = templatePretendService.getFirst(templatePretendQuery);
				if(templatePretend != null && StringUtils.isNotEmpty(templatePretend.getMemIdentity())) {
					member.setMemIdentity(templatePretend.getMemIdentity());
				}
			}
		}

		//悦卡余额
		member.setYueCardCoin(memberCardService.yueCardCoin(memberId));

		//优惠券数量
		member.setCouponNum(couponService.couponNum(busdId,memberId, CouponType.COUPON).intValue());

		//是否有新消息
		member.setHasNewMessage(messageService.setHasNewMessage(busdId,memberId));

		return member;
	}
	@Override
	public Member updateMember(Member member) {
		Check.notEmpty(member.getId(), "id不能为空");
		Member oldMember = getMember(member.getId());
		if (StringUtils.isNotBlank(member.getMobile())
				&& !oldMember.getMobile().equals(member.getMobile())) {
			throw new DragonException(MemberCode.MEMBER_MOBILE_EXIST);
		}
		try {
			if (StringUtils.isNotBlank(member.getNickName())) {
				member.setNickName(EmojiUtil.emojiConvert1(member.getNickName()));
			}
		} catch (UnsupportedEncodingException e) {
			log.error("nickName 转换出错");
			member.setNickName("");
		}
		
		if(StringUtils.isEmpty(member.getAddress())) {
			member.setAddress("暂未填写");
		}
		baseMapper.updateById(member);
		return getMember(member.getId());
	}

	@Override
	public Member modifyLoginPassword(String memberId,String newPassword, String oldPassword) {
		Check.notNull(newPassword, "用户新密码不能为空");

		// 获取当前登录用户信息
		MemberEntity member = getById(memberId);

		// 判断旧密码是否正确
		if (!MD5Util.payMD5(oldPassword).equals(member.getPassword())) {
			throw new DragonException(PayCode.OLD_PASSWORD_IS_ERROR);
		}

		// 修改密码
		member.setPassword(MD5Util.payMD5(newPassword));
		baseMapper.updateById(member);
		return getMember(member.getId());
	}

	@Override
	public Member forgetLoginPassword(PasswordQuery query) {
		Check.notNull(query.getMobile(), "手机号码不能为空");
		Check.notNull(query.getVerifiCode(), "验证码不能为空");
		Check.notNull(query.getNewPassword(), "用户新密码不能为空");

		// 根据手机号查询用户信息
		MemberQuery memberQuery = new MemberQuery();
		memberQuery.setMobile(query.getMobile());
		MemberEntity member = getOne(memberQuery.toQueryWrapper());

		// 修改密码
		member.setPassword(MD5Util.payMD5(query.getNewPassword()));
		baseMapper.updateById(member);
		return getMember(member.getId());
	}

	@Override
	public List<MerchantList> getFavorite(PageRequest page, String busdId,String memberId) {
		List<MerchantList> merchantList = new ArrayList<>();
		// 获取当前登录会员信息
		// 查询当前会员收藏店铺列表
		FavoriteQuery favoriteQuery = new FavoriteQuery();
		favoriteQuery.setMemberId(memberId);
		favoriteQuery.setBusdId(busdId);
		favoriteQuery.setDel(false);
		favoriteQuery.setType(FavoriteType.BUSINESS);
		QueryWrapper<FavoriteEntity> wrapper = favoriteQuery.toQueryWrapper();
		wrapper.orderByDesc(FavoriteEntity.COL_CREATED_TIME);
		IPage<Favorite> iPage = favoriteService.page(PageToResultUtils.resultToPage(page),wrapper);
		for (Favorite favorite : iPage.getRecords()) {
			MerchantList merchantLi = new MerchantList();
			MerchantEntity merchant = merchantService.getById(favorite.getObjectId());
			merchantLi.setId(merchant.getId());
			merchantLi.setLogo(merchant.getMerchantLogo());
			merchantLi.setName(merchant.getMerchantName());
			// 获取该店铺关注总数
			FavoriteQuery query = new FavoriteQuery();
			query.setDel(false);
			query.setObjectId(merchant.getId());
			Long count = favoriteService.count(query.toQueryWrapper());
			merchantLi.setCount(count.intValue());
			// 从缓存中获取美女指数ratio 缓存设置过期时间为1天
			Cache cache = cacheManager.getCache("Ratio");
			if (cache!=null){
				BigDecimal ratio = cache.get(merchant.getId(), BigDecimal.class);
				// 美女指数为空计算美女指数
				if (Objects.isNull(ratio)) {
					BigDecimal setRatio = setRatio(merchant.getId(), busdId);
					cache.put(merchant.getId(), setRatio);
					merchantLi.setRatio(setRatio);
				} else {
					merchantLi.setRatio(ratio);
				}
			}

			merchantList.add(merchantLi);
		}
		return merchantList;
	}

	private BigDecimal setRatio(String merchantId, String busdId) {
		FavoriteQuery favoriteqe = new FavoriteQuery();
		favoriteqe.setObjectId(merchantId);
		favoriteqe.setType(FavoriteType.BUSINESS);
		favoriteqe.setBusdId(busdId);
		favoriteqe.setDel(false);
		List<FavoriteEntity> list = favoriteService.list(favoriteqe.toQueryWrapper());
		Integer count = list.size();
		if (count <= 0) {
			return new BigDecimal(0);
		}
		Integer i = 0;
		for (FavoriteEntity fa : list) {
			Member member = getMember(fa.getMemberId());
			if (Objects.nonNull(member)
					&& Objects.nonNull(member.getGender())
					&& member.getGender().getCode() == 1) {
				i++;
			}
		}
		return new BigDecimal(count - i).divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP);

	}

	@Override
	public void deleteFavorite(String merchantId, String memberId) {
		FavoriteQuery favoriteQuery = new FavoriteQuery();
		favoriteQuery.setMemberId(memberId);
		favoriteQuery.setObjectId(merchantId);
		favoriteService.remove(favoriteQuery.toQueryWrapper());
	}

	@Override
	public String getRecMembers(Integer gender, String memberId) {
		return baseMapper.getRecMembers(gender, memberId);
	}

	/**
	 * 获得会员收藏商品列表
	 * 
	 * @param page     页码
	 * @param busdId   商圈id
	 * @param memberId 会员id
	 * @return
	 */
	@Override
	public List<ProductFavorite> getSpuFavorite(PageRequest page, String busdId, String memberId) {
		FavoriteQuery query = new FavoriteQuery();
		query.setBusdId(busdId);
		query.setMemberId(memberId);
		query.type().ne(FavoriteType.BUSINESS);
		query.setDel(false);
		IPage<Favorite> page1 = favoriteService.page(PageToResultUtils.resultToPage(page), query.toQueryWrapper());
		List<Favorite> favorites = page1.getRecords();
		ArrayList<ProductFavorite> list = new ArrayList<>(favorites.size());
		for (Favorite favorite : favorites) {
			ProductFavorite productFavorite = new ProductFavorite();
			// 拼团
			if (Objects.equals(favorite.getType(), FavoriteType.GROUP)) {
				GrouponInfo groupon = grouponInfoService.getGrouponById(favorite.getObjectId());
				SkuEntity sku = skuService.getById(groupon.getSkuId());
				productFavorite.setGrouponOrHelp(1);
				productFavorite.setId(groupon.getId());
				productFavorite.setMainImg(groupon.getImgs());
				productFavorite.setOriginalPrice(sku.getDiscountPrice());
				productFavorite.setPrice(sku.getOriginalPrice());
				productFavorite.setTitle(groupon.getName());
				productFavorite.setSpuId(sku.getSpuId());
				Boolean expire =(groupon.getIsExpire() || Objects.equals(groupon.getStatus(), GrouponInfoStatus.OFFLINE)
						|| groupon.getEndDate().isBefore(LocalDateTime.now()) || groupon.getDel()
						|| !Objects.equals(groupon.getCheckStatus(), GrouponInfoCheckStatus.THROUGH));
				productFavorite.setExpire(expire);
			}
			// 助力
			if (Objects.equals(favorite.getType(), FavoriteType.HELP)) {
				HelpEntity help = helpService.getById(favorite.getObjectId());
				SkuEntity sku = skuService.getById(help.getSkuId());
				productFavorite.setGrouponOrHelp(0);
				productFavorite.setId(help.getId());
				productFavorite.setMainImg(sku.getMainImages());
				productFavorite.setOriginalPrice(sku.getPrice());
				productFavorite.setPrice(help.getDiscount());
				productFavorite.setTitle(help.getName());
				productFavorite.setSpuId(sku.getSpuId());
				boolean expire = (help.getEndDate().isBefore(LocalDateTime.now())
						|| Objects.equals(help.getStatus(), HelpStatus.STOP)
						|| help.getDel() || help.getIsExpire() != 0
						|| !Objects.equals(help.getCheckStatus(), HelpCheckStatus.THROUGH));
				productFavorite.setExpire(expire);
			}

			list.add(productFavorite);
		}
		return list;
	}

	@Override
	public UserReportModel getUserBaseReport(ReportQuery userReportQuery) {

		if (null != userReportQuery.getPlusDay() && userReportQuery.getPlusDay() > 0) {
			LocalDateTime now = LocalDateTime.now();
			LocalDateTime oldDay = now.minusDays(userReportQuery.getPlusDay());
			LocalDateTime todayStart = LocalDateTime.of(oldDay.toLocalDate(), LocalTime.MIN);// 设置开始日期的零点

			LocalDateTime yesterday = now.minusDays(1);
			LocalDateTime todayEnd = LocalDateTime.of(yesterday.toLocalDate(), LocalTime.MAX);// 当天零点

			userReportQuery.setStartDay(DateUtil.formatStandardDateTime(todayStart));
			userReportQuery.setEndDay(DateUtil.formatStandardDateTime(todayEnd));
		} else {
			String startDay = userReportQuery.getStartDay();
			String endDay = userReportQuery.getEndDay();
			userReportQuery.setStartDay(startDay + " 00:00:00");
			userReportQuery.setEndDay(endDay + " 23:59:59");
		}

		UserReportModel userBaseInfo = baseMapper.getUserBaseInfo(userReportQuery);
		getSequentialReportQuery(userReportQuery);

		Integer sequentialUserAdd = baseMapper.getSequentialUserAdd(userReportQuery);
		BigDecimal sequentialUA = new BigDecimal(sequentialUserAdd);
		// 计算环比
		userBaseInfo = null == userBaseInfo ? new UserReportModel() : userBaseInfo;
		if (null == userBaseInfo.getNewUserNum()) {
			userBaseInfo.setNewUserNum(0);
		}
		BigDecimal sequentialAdd = BigDecimal.ZERO;
		BigDecimal decimal = new BigDecimal(userBaseInfo.getNewUserNum());
		if (sequentialUA.compareTo(BigDecimal.ZERO) > 0 && decimal.compareTo(sequentialAdd) > 0) {
			sequentialAdd = decimal.subtract(sequentialUA).divide(sequentialUA, 2, BigDecimal.ROUND_HALF_UP)
					.multiply(new BigDecimal(100));
		}
		userBaseInfo.setSequentialAdd(sequentialAdd);
		return userBaseInfo;
	}

	private void getSequentialReportQuery(ReportQuery reportQuery) {

		LocalDateTime startDay = DateUtil.parseDate(reportQuery.getStartDay());
		LocalDateTime endDay = DateUtil.parseDate(reportQuery.getEndDay());

		Duration between = Duration.between(startDay, endDay);
		LocalDateTime sequentialDay = startDay.minusDays(between.toDays() + 1);

		reportQuery.setStartDay(DateUtil.formatStandardDateTime(sequentialDay));
		reportQuery.setEndDay(DateUtil.formatStandardDateTime(startDay));

	}

	@Override
	@SuppressWarnings("all")
	public UserReportModel getAllUserReport(ReportQuery userReportQuery) {
		// 会员性别对比
		List<Map> useGenderTotal = baseMapper.getUseGenderTotal(userReportQuery.getBusdId());
		// 年龄阶段
		List<Map> useAgeGroupTotal = baseMapper.getUseAgeGroupTotal(userReportQuery.getBusdId());
		// 星座
		List<Map> useBirthTotal = baseMapper.getUseBirthTotal(userReportQuery.getBusdId());
		// 是否有车
		Map userHasCarTotal = baseMapper.getUseHasCarTotal(userReportQuery.getBusdId());

		UserReportModel model = new UserReportModel();

		String[] gender = { "男", "女", "未知" };
		Integer[] genderValue = new Integer[3];
		for (Map map : useGenderTotal) {
			Integer gn = Integer.valueOf(String.valueOf(map.get("gender")));
			Integer cnt = Integer.valueOf(String.valueOf(map.get("cnt")));
			if (0 == gn.intValue()) {
				genderValue[2] = cnt;
			} else if (1 == gn.intValue()) {
				genderValue[0] = cnt;
			} else if (2 == gn.intValue()) {
				genderValue[1] = cnt;
			}
		}
		model.setGenderKey(gender);
		model.setGenderValue(genderValue);

		String[] ageGroup = new String[useAgeGroupTotal.size()];
		Integer[] ageGroupValue = new Integer[useAgeGroupTotal.size()];
		for (int i = 0; i < useAgeGroupTotal.size(); i++) {
			Map map = useAgeGroupTotal.get(i);
			ageGroup[i] = (String) map.get("age_group");
			ageGroupValue[i] = Integer.valueOf(String.valueOf(map.get("cnt")));
		}
		model.setAgeGroupKey(ageGroup);
		model.setAgeGroupValue(ageGroupValue);

		String[] brth = new String[useBirthTotal.size()];
		Integer[] brthValue = new Integer[useBirthTotal.size()];
		for (int i = 0; i < useBirthTotal.size(); i++) {
			Map map = useBirthTotal.get(i);
			brth[i] = (String) map.get("birth");
			brthValue[i] = Integer.valueOf(String.valueOf(map.get("cnt")));
		}
		model.setBrthKey(brth);
		model.setBrthValue(brthValue);

		String[] hasCar = { "有车一族", "环保出行" };
		Integer[] hasCarValue = new Integer[2];
		Integer total = Integer.valueOf(String.valueOf(userHasCarTotal.get("total")));
		Integer hascar = Integer.valueOf(String.valueOf(userHasCarTotal.get("hascar")));
		hasCarValue[0] = hascar;
		hasCarValue[1] = total - hascar;

		model.setHasCarKey(hasCar);
		model.setHasCarValue(hasCarValue);

		return model;
	}

	@Override
	public IPage<UserInfoModel> getUserInfoList(PageRequest page, ReportQuery userReportQuery) {

		IPage<UserInfoModel> salesPage = baseMapper.getUserInfoList(PageToResultUtils.resultToPage(page), userReportQuery);

		if (null != salesPage && CollectionUtils.isNotEmpty(salesPage.getRecords())) {
			salesPage.getRecords().stream().forEach(this::fillUserInfo);
		}

		return salesPage;
	}

    @Override
    public Document getMemberTemplate() {
        ExportMemberWorkbook recoedWorkbook = new ExportMemberWorkbook();
        return documentService.generateExcel("会员模板.xlsx", recoedWorkbook);
    }

	@Override
	public void importMember(MultipartFile file, String busdId) {
		ExportMemberWorkbook employeeWorkbook = null;
		ReadExcelHelper helper = new ReadExcelHelper();
		try {
			employeeWorkbook = helper.readExcel(file, ExportMemberWorkbook.class);
		} catch (Exception e){
			log.error("导入会员表错误,"+e);
			throw new DragonException(10002,"格式错误");
		}
		if (employeeWorkbook == null || CollectionUtils.isEmpty(employeeWorkbook.getMember())) {
			return;
		}
		// 检索数据
		checkRows(employeeWorkbook);

		// 检索通过以后则对数据进行操作
		employeeWorkbook.getMember().stream().forEach(row -> updateMember(row,busdId));
	}

	private void updateMember(ExportMemberWorkbook.MemberRow row,String busdId){
		// 判断会员，会员和商圈的关系是否存在 存在则直接返回会员ID不存在则创建再返回会员ID
		String memberId = detailService.checkMember(row.getMobile(), busdId);
		MemberEntity member = getById(memberId);
		if ((member.getGender()==null|| MemberGender.UNKNOWN.equals(member.getGender()))&&StringUtils.isNotEmpty(row.getGender())){
			member.setGender(MemberGender.fromAlias(row.getGender()));
		}
		if (StringUtils.isEmpty(member.getNickName()) &&StringUtils.isNotEmpty(row.getNickName())){
			member.setNickName(row.getNickName());
		}
		if ( member.getBirthDate()==null &&row.getBirthDay()!=null){
			member.setBirthDate(row.getBirthDay());
		}
		if (StringUtils.isEmpty(member.getAddress()) &&StringUtils.isNotEmpty(row.getAddress())){
			member.setAddress(row.getAddress());
		}
		baseMapper.updateById(member);
	}

	@Override
	public Boolean judge(String memberId) {
		if (StringUtils.isEmpty(memberId)){
			return false;
		}
		Member member = memberCache.get(memberId, Member.class);
		MemberEntity entity = getById(memberId);
		if (StringUtils.isEmpty(entity.getNickName())
				|| StringUtils.isEmpty(entity.getHeadImg())
				|| entity.getGender().equals(MemberGender.UNKNOWN)) {
			Member member1 = new Member(entity);
			member1.setRequestLoginTime(LocalDate.now());
			if (member == null) {
				memberCache.put(memberId, member1);
			} else {
				LocalDate requestLoginTime = member.getRequestLoginTime();
				if (LocalDate.now().toEpochDay() - requestLoginTime.toEpochDay() < 7L) {
					return false;
				} else {
					memberCache.evict(memberId);
					memberCache.put(memberId, member1);
				}
			}
			return true;
		} else {
			if (member != null) {
				memberCache.evict(memberId);
			}
		}
		return false;
	}

	@Override
	public Member getMemberByAliAppid(String appId) {
		if (StringUtils.isBlank(appId)) {
			return null;
		}
		// 判断会员是否存在
		WxOpenidRefQuery query = new WxOpenidRefQuery();
		query.setAliAppid(appId);
		WxOpenidRef wxOpenidRef = wxOpenidRefService.getFirst(query);
		if (wxOpenidRef != null && wxOpenidRef.getMemberId() != null) {
			String memberId = wxOpenidRef.getMemberId();
			return this.getMember(memberId);
		}
		return null;
	}

	private void checkRows(ExportMemberWorkbook employeeWorkbook) {
		// 获取数据集合
		List<ExportMemberWorkbook.MemberRow> rowList = employeeWorkbook.getMember();
		List<ValidateResult> validateInfo = new ArrayList<>();
		for (int i = 0; i < rowList.size(); i++) {
			ExportMemberWorkbook.MemberRow row = rowList.get(i);
			// 判断手机号码是否为空
			if (row.getMobile() == null) {
				validateInfo.add(new ValidateResult("会员导入", "员工手机号", i + 1, row.getMobile(), "手机号不能为空 "));
			}
			// 判断手机号码格式是否正确
			if (!PrivateStringUtils.isMobileNO(row.getMobile())) {
				validateInfo.add(new ValidateResult("会员导入", "员工手机号", i + 1, row.getMobile(), "手机号格式不正确 "));
			}
			if (StringUtils.isNotEmpty(row.getNickName()) && row.getNickName().length() > 100) {
				validateInfo.add(new ValidateResult("会员导入", "用户名", i + 1, row.getNickName(), "长度超过限制 "));
			}
			if (StringUtils.isNotEmpty(row.getGender())&&MemberGender.fromAlias(row.getGender())==null) {
				validateInfo.add(new ValidateResult("会员导入", "性别", i + 1, row.getGender(), "不符合规范 "));
			}
			if (StringUtils.isNotEmpty(row.getAddress()) && row.getAddress().length() > 200) {
				validateInfo.add(new ValidateResult("会员导入", "地址", i + 1, row.getAddress(), "长度超过限制 "));
			}
		}
		// 数据校验不通过则抛出错误
		if (CollectionUtils.isNotEmpty(validateInfo)) {
			throw new DragonException(MemberCode.MEMBER_POINT_INCORRECT_DATA.getCode(), validateInfo.toString());
		}
	}

	private void fillUserInfo(UserInfoModel userInfoModel) {
		// 查询是否有车
		HistoryQuery historyQuery = new HistoryQuery();
		historyQuery.memberId().eq(userInfoModel.getId());
		Long count = historyService.count(historyQuery.toQueryWrapper());
		userInfoModel.setHasCar(count > 0 ? "有车一族" : "环保出行");

		OrderQuery orderQuery = new OrderQuery();
		orderQuery.buyerId().eq(userInfoModel.getId());
		List<OrderEntity> list = orderService.list(orderQuery.toQueryWrapper());
		Set<String> set = new HashSet<>();
		BigDecimal totalAmount = BigDecimal.ZERO;
		for (OrderEntity order : list) {
			Order ord = orderService.getOrder(order.getId());
			totalAmount = totalAmount.add(ord.getPayAmount());
			MerchantEntity merchant = merchantService.getById(ord.getMerchantId());
			if (null != merchant) {
				BtypeEntity btype = btypeService.getById(merchant.getBtypeSecondId());
				set.add(btype.getName());
			}
		}
		userInfoModel.setPreferences(set.toString().replace("[", "").replace("]", ""));
		userInfoModel.setActive(this.setActive(list.size()));
		userInfoModel.setUserValue(this.setUserValue(totalAmount));
	}

	private String setActive(int listSize){
		if (listSize > 4){
			return "高";
		}
		if (listSize > 2){
			return "中";
		}
		return "低";
	}

	private String setUserValue(BigDecimal totalAmount){
		if (totalAmount.compareTo(new BigDecimal( 1000))>0){
			return "高";
		}
		if (totalAmount.compareTo(new BigDecimal( 500))>0){
			return "中";
		}
		return "低";
	}
}